home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / pbmplus / ppm / libppm4.c < prev    next >
Text File  |  1996-02-28  |  8KB  |  309 lines

  1. /* libppm4.c - ppm utility library part 4
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "ppm.h"
  14.  
  15. static void
  16. canonstr( str )
  17.     char* str;
  18.     {
  19.     while ( *str != '\0' )
  20.     {
  21.     if ( *str == ' ' )
  22.         {
  23.         (void) strcpy( str, &(str[1]) );
  24.         continue;
  25.         }
  26.     if ( isupper( *str ) )
  27.         *str = tolower( *str );
  28.     ++str;
  29.     }
  30.     }
  31.  
  32. static long
  33. rgbnorm( rgb, lmaxval, n, colorname )
  34.     long rgb, lmaxval;
  35.     int n;
  36.     char* colorname;
  37.     {
  38.     switch ( n )
  39.     {
  40.     case 1:
  41.     if ( lmaxval != 15 )
  42.         rgb = rgb * lmaxval / 15;
  43.     break;
  44.     case 2:
  45.     if ( lmaxval != 255 )
  46.         rgb = rgb * lmaxval / 255;
  47.     break;
  48.     case 3:
  49.     if ( lmaxval != 4095 )
  50.         rgb = rgb * lmaxval / 4095;
  51.     break;
  52.     case 4:
  53.     if ( lmaxval != 65535L )
  54.         rgb = rgb * lmaxval / 65535L;
  55.     break;
  56.     default:
  57.     pm_error( "invalid color specifier - \"%s\"", colorname );
  58.     }
  59.     return rgb;
  60.     }
  61.  
  62. #if __STDC__
  63. pixel
  64. ppm_parsecolor( char* colorname, pixval maxval )
  65. #else /*__STDC__*/
  66. pixel
  67. ppm_parsecolor( colorname, maxval )
  68.     char* colorname;
  69.     pixval maxval;
  70. #endif /*__STDC__*/
  71.     {
  72.     int hexit[256], i;
  73.     pixel p;
  74.     long lmaxval, r, g, b;
  75.     char* inval = "invalid color specifier - \"%s\"";
  76.  
  77.     for ( i = 0; i < 256; ++i )
  78.     hexit[i] = 1234567890;
  79.     hexit['0'] = 0;
  80.     hexit['1'] = 1;
  81.     hexit['2'] = 2;
  82.     hexit['3'] = 3;
  83.     hexit['4'] = 4;
  84.     hexit['5'] = 5;
  85.     hexit['6'] = 6;
  86.     hexit['7'] = 7;
  87.     hexit['8'] = 8;
  88.     hexit['9'] = 9;
  89.     hexit['a'] = hexit['A'] = 10;
  90.     hexit['b'] = hexit['B'] = 11;
  91.     hexit['c'] = hexit['C'] = 12;
  92.     hexit['d'] = hexit['D'] = 13;
  93.     hexit['e'] = hexit['E'] = 14;
  94.     hexit['f'] = hexit['F'] = 15;
  95.  
  96.     lmaxval = maxval;
  97.     if ( strncmp( colorname, "rgb:", 4 ) == 0 )
  98.     {
  99.     /* It's a new-X11-style hexadecimal rgb specifier. */
  100.     char* cp;
  101.  
  102.     cp = colorname + 4;
  103.     r = g = b = 0;
  104.     for ( i = 0; *cp != '/'; ++i, ++cp )
  105.         r = r * 16 + hexit[*cp];
  106.     r = rgbnorm( r, lmaxval, i, colorname );
  107.     for ( i = 0, ++cp; *cp != '/'; ++i, ++cp )
  108.         g = g * 16 + hexit[*cp];
  109.     g = rgbnorm( g, lmaxval, i, colorname );
  110.     for ( i = 0, ++cp; *cp != '\0'; ++i, ++cp )
  111.         b = b * 16 + hexit[*cp];
  112.     b = rgbnorm( b, lmaxval, i, colorname );
  113.     if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
  114.         pm_error( inval, colorname );
  115.     }
  116.     else if ( strncmp( colorname, "rgbi:", 5 ) == 0 )
  117.     {
  118.     /* It's a new-X11-style decimal/float rgb specifier. */
  119.     float fr, fg, fb;
  120.  
  121.     if ( sscanf( colorname, "rgbi:%f/%f/%f", &fr, &fg, &fb ) != 3 )
  122.         pm_error( inval, colorname );
  123.     if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
  124.         pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
  125.     r = fr * lmaxval;
  126.     g = fg * lmaxval;
  127.     b = fb * lmaxval;
  128.     }
  129.     else if ( colorname[0] == '#' )
  130.     {
  131.     /* It's an old-X11-style hexadecimal rgb specifier. */
  132.     switch ( strlen( colorname ) )
  133.         {
  134.         case 4:
  135.         r = hexit[colorname[1]];
  136.         g = hexit[colorname[2]];
  137.         b = hexit[colorname[3]];
  138.         r = rgbnorm( r, lmaxval, 1, colorname );
  139.         g = rgbnorm( g, lmaxval, 1, colorname );
  140.         b = rgbnorm( b, lmaxval, 1, colorname );
  141.         break;
  142.  
  143.         case 7:
  144.         r = ( hexit[colorname[1]] << 4 ) + hexit[colorname[2]];
  145.         g = ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
  146.         b = ( hexit[colorname[5]] << 4 ) + hexit[colorname[6]];
  147.         r = rgbnorm( r, lmaxval, 2, colorname );
  148.         g = rgbnorm( g, lmaxval, 2, colorname );
  149.         b = rgbnorm( b, lmaxval, 2, colorname );
  150.         break;
  151.  
  152.         case 10:
  153.         r = ( hexit[colorname[1]] << 8 ) + ( hexit[colorname[2]] << 4 ) +
  154.         hexit[colorname[3]];
  155.         g = ( hexit[colorname[4]] << 8 ) + ( hexit[colorname[5]] << 4 ) +
  156.         hexit[colorname[6]];
  157.         b = ( hexit[colorname[7]] << 8 ) + ( hexit[colorname[8]] << 4 ) +
  158.         hexit[colorname[9]];
  159.         r = rgbnorm( r, lmaxval, 3, colorname );
  160.         g = rgbnorm( g, lmaxval, 3, colorname );
  161.         b = rgbnorm( b, lmaxval, 3, colorname );
  162.         break;
  163.  
  164.         case 13:
  165.         r = ( hexit[colorname[1]] << 12 ) + ( hexit[colorname[2]] << 8 ) +
  166.         ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
  167.         g = ( hexit[colorname[5]] << 12 ) + ( hexit[colorname[6]] << 8 ) +
  168.         ( hexit[colorname[7]] << 4 ) + hexit[colorname[8]];
  169.         b = ( hexit[colorname[9]] << 12 ) + ( hexit[colorname[10]] << 8 ) +
  170.         ( hexit[colorname[11]] << 4 ) + hexit[colorname[12]];
  171.         r = rgbnorm( r, lmaxval, 4, colorname );
  172.         g = rgbnorm( g, lmaxval, 4, colorname );
  173.         b = rgbnorm( b, lmaxval, 4, colorname );
  174.         break;
  175.  
  176.         default:
  177.         pm_error( inval, colorname );
  178.         }
  179.     if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
  180.         pm_error( inval, colorname );
  181.     }
  182.     else if ( ( colorname[0] >= '0' && colorname[0] <= '9' ) ||
  183.           colorname[0] == '.' )
  184.     {
  185.     /* It's an old-style decimal/float rgb specifier. */
  186.     float fr, fg, fb;
  187.  
  188.     if ( sscanf( colorname, "%f,%f,%f", &fr, &fg, &fb ) != 3 )
  189.         pm_error( inval, colorname );
  190.     if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
  191.         pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
  192.     r = fr * lmaxval;
  193.     g = fg * lmaxval;
  194.     b = fb * lmaxval;
  195.     }
  196.     else
  197.     {
  198.     /* Must be a name from the X-style rgb file. */
  199. #ifndef RGB_DB
  200.     pm_error( "color names database required - please reconfigure with RGBDEF" );
  201. #else /*RGB_DB*/
  202.     FILE* f;
  203.     char buf1[200], buf2[200];
  204.  
  205.     (void) sprintf( buf1, "%s.txt", RGB_DB );
  206.     if ( ( f = fopen( buf1, "r" ) ) == NULL )
  207.         pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
  208.     canonstr( colorname );
  209.     while ( fgets( buf1, sizeof(buf1), f ) != NULL )
  210.         {
  211.         if ( sscanf( buf1, "%ld %ld %ld %[^\n]", &r, &g, &b, buf2 ) != 4 )
  212.         {
  213.         pm_message(
  214.             "can't parse color names database line - \"%s\"", buf1 );
  215.         continue;
  216.         }
  217.         canonstr( buf2 );
  218.         if ( strcmp( colorname, buf2 ) == 0 )
  219.         goto gotit;
  220.         }
  221.     (void) fclose( f );
  222.     pm_error( "unknown color - \"%s\"", colorname );
  223.  
  224. gotit:
  225.     (void) fclose( f );
  226.     /* Rescale from [0..255] if necessary. */
  227.     if ( lmaxval != 255 )
  228.         {
  229.         r = r * lmaxval / 255;
  230.         g = g * lmaxval / 255;
  231.         b = b * lmaxval / 255;
  232.         }
  233. #endif /*RGB_DB*/
  234.     }
  235.  
  236.     PPM_ASSIGN( p, r, g, b );
  237.     return p;
  238.     }
  239.  
  240. static char colorname[200];
  241.  
  242. #if __STDC__
  243. char*
  244. ppm_colorname( pixel* colorP, pixval maxval, int hexok )
  245. #else /*__STDC__*/
  246. char*
  247. ppm_colorname( colorP, maxval, hexok )
  248.     pixel* colorP;
  249.     pixval maxval;
  250.     int hexok;
  251. #endif /*__STDC__*/
  252.     {
  253.     int r, g, b;
  254. #ifdef RGB_DB
  255.     FILE* f;
  256.     char buf[200];
  257.     int this_r, this_g, this_b;
  258.     int best_diff, this_diff;
  259.     char this_colorname[200];
  260. #endif /*RGB_DB*/
  261.  
  262.     if ( maxval == 255 )
  263.     {
  264.     r = PPM_GETR( *colorP );
  265.     g = PPM_GETG( *colorP );
  266.     b = PPM_GETB( *colorP );
  267.     }
  268.     else
  269.     {
  270.     r = (int) PPM_GETR( *colorP ) * 255 / (int) maxval;
  271.     g = (int) PPM_GETG( *colorP ) * 255 / (int) maxval;
  272.     b = (int) PPM_GETB( *colorP ) * 255 / (int) maxval;
  273.     }
  274.  
  275. #ifdef RGB_DB
  276.     (void) sprintf( buf, "%s.txt", RGB_DB );
  277.     if ( ( f = fopen( buf, "r" ) ) == NULL )
  278.     pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
  279.     best_diff = 32767;
  280.     while ( fgets( buf, sizeof(buf), f ) != NULL )
  281.     {
  282.     if ( sscanf( buf, "%d %d %d %[^\n]", &this_r, &this_g, &this_b,
  283.              this_colorname ) != 4 )
  284.         {
  285.         pm_message(
  286.         "can't parse color names database line - \"%s\"",
  287.         buf );
  288.         continue;
  289.         }
  290.     this_diff = abs( r - this_r ) + abs( g - this_g ) + abs( b - this_b );
  291.     if ( this_diff < best_diff )
  292.         {
  293.         best_diff = this_diff;
  294.         (void) strcpy( colorname, this_colorname );
  295.         }
  296.     }
  297.     (void) fclose( f );
  298.     if ( best_diff != 32767 && ( best_diff == 0 || ! hexok ) )
  299.     return colorname;
  300. #endif /*RGB_DB*/
  301.  
  302.     /* Color lookup failed; generate an X11-style hex specifier. */
  303.     if ( ! hexok )
  304.     pm_error(
  305.         "color names database required - please reconfigure with RGBDEF" );
  306.     sprintf( colorname, "#%02x%02x%02x", r, g, b );
  307.     return colorname;
  308.     }
  309.